﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CoreCalc;
using RayDen.Library.Core.Primitives;
using RayDen.Library.Data.Imaging;

namespace RayDen.Library.Components.Color.Types
{
    public class PointSampledSpectrum : BaseColorType<PointSampledSpectrum>
    {
        protected SampledSpectrum spd;

        public override PointSampledSpectrum Value
        {
            get { return this; }
        }

        public PointSampledSpectrum()
        {
            spd = new SampledSpectrum();
        }

        public PointSampledSpectrum(ref RgbSpectrum rgb, SpectrumType type = SpectrumType.Reflectance)
        {
            spd = ColorFactory.SSEFromRgb(ref rgb, type);
        }
        public PointSampledSpectrum(RgbSpectrumInfo rgb, SpectrumType type = SpectrumType.Reflectance)
        {
            spd = ColorFactory.SSEFromRgb(rgb.ToArray(), type);
        }

        public PointSampledSpectrum(ref SampledSpectrum spd)
        {
            this.spd = spd;
        }

        public PointSampledSpectrum(PointSampledSpectrum spd)
        {
            this.spd = spd.spd;
        }

        public override bool IsBlack()
        {
            return spd.IsBlack();
        }

        public override float Filter()
        {
            return this.spd.Filter();
        }

        public override void ToZero()
        {
            for (int i = 0; i < SampledSpectrum.nSamples; i++)
                this.spd[i] = 0f;
        }

        public override void ToUnit()
        {
            for (int i = 0; i < SampledSpectrum.nSamples; i++)
                this.spd[i] = 1f;
        }

        public override RgbSpectrum ToXyz()
        {
            return spd.ToXyz();
        }

        public override float Sample(float lambda)
        {
            var lambdas = Enumerable.Range(0, 
                SampledSpectrum.nSpectralSamples).Select((i, n) => new Tuple<int, float>(n, lambda - (float)(SampledSpectrum.sampledLambdaStart + i * (SampledSpectrum.nSpectralSamples)))).OrderBy(t => t.Item2).First();

            return this.spd[lambdas.Item1];
        }

        public override void TransformToRgb(out RgbSpectrum result)
        {
            result = spd.ToRgb();
        }

        protected override BaseColorType<PointSampledSpectrum> Add(BaseColorType<PointSampledSpectrum> v)
        {
            SSE.AddSSE(ref this.spd, ref v.Value.spd,ref this.spd );
            //this.spd += v.Value.spd;
            return this;
        }

        protected override BaseColorType<PointSampledSpectrum> Mul(BaseColorType<PointSampledSpectrum> v)
        {
            //this.spd *= v.Value.spd;
            SSE.MulSSE(ref this.spd, ref v.Value.spd, ref this.spd);
            return this;
        }

        protected override BaseColorType<PointSampledSpectrum> AddFloat(float v)
        {
            SSE.AddSSE(ref this.spd, v, ref this.spd);

            return this;
        }

        protected override BaseColorType<PointSampledSpectrum> MulFloat(float v)
        {
            SSE.MulSSE(ref this.spd, v, ref this.spd);
            return this;
        }

        public override IColorType CloneValue()
        {
            return new PointSampledSpectrum(this);
        }
    }
}
